// Michael Moriarty
// OpenCV Assignment 1
// Started and finished: 2/2/08

#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#include <string>
using namespace std;

#define IMG(img,i,j) (*(unsigned char *)((img)->imageData + (i)*(img)->widthStep+ (j)))

int main(int argc, char* argv[]) 
{
	char debug = 0;
	string outfile = "out.png";
	string infile = "";
	float pupx = 0.0, pupy = 0.0, puprad = 0.0;
	float irisx = 0.0, irisy = 0.0, irisrad = 0.0;

	// usage statement
	if (argc <= 1)
	{
		fprintf(stderr,"Usage: %s [opts] \n",argv[0]);
		fprintf(stderr,"opts: [-d] for debug, -i infile, [-o outfile] (default out.png), [-t for test case], -x for pupil x coordinate, -y for pupil y coordinate, -r for pupil radius, -X for iris x coord, -Y for iris y coord, -R for iris radius\n");
		exit(-1);
	}

	// processing command line opts 
	while(1) 
	{
		int c = getopt(argc,argv,"tdx:y:r:X:Y:R:o:i:");
		if (c == -1) break;
		switch(c) 
		{
			case 'd': debug = 1; break;
			case 'o': outfile = optarg; break;
			case 'i': infile = optarg; break;
			case 'x': pupx = atof(optarg); break;
			case 'y': pupy = atof(optarg); break;
			case 'r': puprad = atof(optarg); break;
			case 'X': irisx = atof(optarg); break;
			case 'Y': irisy = atof(optarg); break;
			case 'R': irisrad = atof(optarg); break;						
			case 't': infile = "data.txt"; break;
			case '?': fprintf(stderr,"FAIL: malformed option list\n");
		}
	}
	
	if (debug)
	{
		cout << "Debugging." << endl;
		cout << "Outfile: " << outfile << endl;
		cout << "Infile: " << infile << endl;
		cout << "Pupil center (x,y,rad): " << pupx << " " << pupy << " " << puprad << endl;
		cout << "Iris center (x,y,rad): " << irisx << " " << irisy << " " << irisrad << endl;
	}
	
	// show the image in a window of appropriate size
	
	IplImage* src = cvLoadImage(infile.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
	if (debug)
	{
		cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
		cvShowImage("Original Image", src);
	}
	
	// copy the image
	IplImage* cp = cvCreateImage(cvGetSize(src), 8, 1);
	cvCopyImage(src, cp);
	
	IplImage* unwrap = cvCreateImage(cvSize(480,40), 8, 1);
	cout << unwrap->height << " " << unwrap->width << endl;
	
	
	float theta = 0.0;
	float x_pol = 0.0, y_pol = 0.0, r = 0.0, vect_norm = 0.0;
	//int val = 0;
	CvScalar val;
	for (int col = 0; col < 480; col++)
	{
		
		for (int row = 0; row < 40; row++)
		{ 
			
			r = 1 - (row/40.0);
			//cout << r << endl;
			theta = col * ((2 * 3.141)/480);
			x_pol = floor(((1-r) * (pupx+(puprad*cos(theta)))) + (r * (irisx+(irisrad*cos(theta)))));
			y_pol = floor(((1-r) * (pupy+(puprad*sin(theta)))) + (r * (irisy+(irisrad*sin(theta)))));
			//cout << x_pol << " " << y_pol << endl;
			
			val = cvGet2D(src,cvRound(y_pol),cvRound(x_pol));
			//cout << val.val[0] << endl;
			cvSet2D(unwrap,row,col,val);
			//cout << row << " " << col << endl;
				
			
		
		}
	}
	

		/*
		# use the normalized vector to step inside and outside of the circle
		j_index = cvRound(math.floor(i_theta) + 3*vect[0])
		if j_index >= src.width:
			j_index = src.width-1
		i_index = cvRound(math.floor(j_theta) + 3*vect[1])
		if i_index >= src.height:
			i_index = src.height-1
		j_index_2 = cvRound(math.floor(i_theta) - 3*vect[0])
		if j_index_2 >= src.width:
			j_index_2 = src.width-1
		i_index_2 = cvRound(math.floor(j_theta) - 3*vect[1])
		if i_index_2 >= src.height:
			i_index_2 = src.height-1
			
		if j_index < 0:
			j_index = 1
		if i_index < 0:
			i_index = 1
		if j_index_2 < 0:
			j_index_2 = 1
		if i_index_2 < 0:
			i_index_2 = 1
		
		ct = ct + 1*/
		
	if (debug)
	{
		cvNamedWindow("Unwrapped Image", CV_WINDOW_AUTOSIZE);
		cvShowImage("Unwrapped Image", unwrap);
	}	
	
	if (debug)
		cvWaitKey(0);
	
	string o = "_unwrapped.png";
	infile.replace(infile.find(".tif"),o.size(),o);
	cvSaveImage(outfile.c_str(),unwrap);
	
	return 0;
	
		/*	# find the point in Cartesian coordinates of the circle in question
		theta = math.radians(i)
		j_theta = float(circle[1]) + (float(circle[2]) * math.cos(theta))
		i_theta = float(circle[0]) + (float(circle[2]) * math.sin(theta))
		
		# normalize the vector from the circle's origin to the point on the edge
		v = (float(circle[0]) - i_theta, float(circle[1]) - j_theta)
		vect_norm = math.sqrt(v[0]**2 + v[1]**2)
		vect = (v[0]/vect_norm,v[1]/vect_norm)*/
		
}
